package com.hk.common.websocket;

import com.alibaba.fastjson2.JSONObject;
import com.hk.common.constant.Constants;
import com.hk.common.constant.MsgException;
import com.hk.common.utils.UuidUtils;
import com.hk.common.websocket.bean.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class WebsocketHandler extends TextWebSocketHandler implements Serializable {

	private static final long serialVersionUID = 1L;

	private static final Map<String, WebSocketSession> webSocketMap = new HashMap<String, WebSocketSession>();


	/** 日志 */
	private static Logger logger = LoggerFactory.getLogger(WebsocketHandler.class);

	/**
	 * 处理客户端发送的消息
     * @date 2019-03-14
     * @authoer zhangyu
	 */
	@Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
		String physicIp = (String) session.getAttributes().get(Constants.CLIENT_IP);
		// 构建消息数据
        Operation operation = parseOperation(message);
        // 前端可能没有添加IP 这里添加IP
        operation.setClientIP(physicIp);
		if(Operation.OperationCodeEnum.heart_beat.equals(operation.getCode())){
            sendOperationToClient(operation);
            webSocketMap.put(physicIp,session);
        }
	}

	/**
	 * 成功连接
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session) {
		String physicIp = (String) session.getAttributes().get(Constants.CLIENT_IP);
        webSocketMap.put(physicIp,session);
	}

	/**
	 * 出现异常的时候
	 */
	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) {
        String physicIp = (String) session.getAttributes().get(Constants.CLIENT_IP);
        webSocketMap.remove(physicIp);
	}

	/**
	 * 连接断开时
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        String physicIp = (String) session.getAttributes().get(Constants.CLIENT_IP);
	    webSocketMap.remove(physicIp);
	}

    /**
     * 转换为 Operation
     * @param textMessage
     * @return
     */
	private static Operation parseOperation(TextMessage textMessage){
        return JSONObject.parseObject(textMessage.getPayload(), Operation.class);
    }

    /**
     * 转换为 TextMessage
     * @param operation
     * @return
     */
    private static TextMessage parseTextMsg(Operation operation){
        return new TextMessage(JSONObject.toJSONString(operation));
    }


    /**
     * 发消息到客户端
     * 参数o中的clientIp为目标IP
     * ！！！不需要外部异常处理的调用此接口
     * @author zhangyu
     * @date 2023-12-22
     */
    public static void sendOperaToClient(Operation o) {
        o.setUuid(UuidUtils.shortUuid());
        try{
            TextMessage msg = parseTextMsg(o);
            WebSocketSession clientSession = webSocketMap.get(o.getClientIP());
            if (clientSession != null) {
                synchronized (webSocketMap) {
                    try {
                        clientSession.sendMessage(msg);
                    } catch (IOException e) {
                        e.printStackTrace();
                        logger.error("发送消息给用户时，发生IOException,e:"+e.getMessage());
                    }
                }
            }else{
                logger.error("未找到连接的用户,IP:"+o.getClientIP());
            }
        }catch (Exception e){
            logger.error("发送消息到前端异常,e:",e);
        }
    }

    /**
     * 发消息到客户端
     * 参数o中的clientIp为目标IP
     * @author zhangyu
     * @date 2019-03-28
     */
    public static void sendOperationToClient(Operation o) throws Exception{
        TextMessage msg = parseTextMsg(o);
        WebSocketSession clientSession = webSocketMap.get(o.getClientIP());
        if (clientSession != null) {
            synchronized (clientSession) {
                try {
                    clientSession.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("发送消息给用户时，发生IOException,e:"+e.getMessage());
                    throw e;
                }
            }
        }else{
            throw new MsgException("未找到连接的用户,IP:"+o.getClientIP());
        }
    }

    /**
     * 发送操作到所有用户
     * 参数o中的clientIp将被忽略
     * @param o
     * @author zhangyu
     * @date 2019-03-29
     */
    public static void sendOperationToAllClient(Operation o){
        TextMessage msg =new TextMessage(JSONObject.toJSONString(o));
        Iterator<Map.Entry<String, WebSocketSession>> it = webSocketMap.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String, WebSocketSession> en = it.next();
            WebSocketSession clientSession = en.getValue();
            if (clientSession != null) {
                synchronized (clientSession) {
                    try {
                        clientSession.sendMessage(msg);
                    } catch (IOException e) {
                        e.printStackTrace();
                        logger.error("发送消息给用户时，发生IOException,e:"+e.getMessage());
                    }
                }
            }
        }
    }

}
